package cn.com.dingtek.genius.manager.server.service;

import cn.com.dingtek.genius.manager.server.repository.db.entity.CompanyDeviceWeb;
import cn.com.dingtek.genius.manager.server.repository.db.entity.DeviceBase;
import cn.com.dingtek.genius.manager.server.repository.db.manager.CompanyDeviceWebManager;
import cn.com.dingtek.genius.manager.server.repository.db.manager.DeviceBaseManager;
import cn.com.dingtek.genius.manager.server.support.DeviceSocket;
import cn.com.dingtek.genius.manager.server.support.DeviceType;
import cn.com.dingtek.genius.manager.server.support.PlatformType;
import cn.com.dingtek.genius.manager.server.support.ToWebType;
import cn.com.dingtek.genius.manager.server.utils.MybatisPlusUtil;
import cn.com.dingtek.genius.manager.server.utils.Verify;
import cn.com.dingtek.genius.manager.server.utils.VerifyException;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

@Slf4j
@Service
public class DeviceUnbindService {
    @Autowired
    private DeviceBaseManager deviceBaseManager;
    @Autowired
    private CompanyDeviceWebManager companyDeviceWebManager;

    public JSONObject list(DeviceBase param, int currentPage, int pageSize) {
        QueryWrapper<DeviceBase> query = Wrappers.<DeviceBase>query().isNull("company_id");
        if (param != null) {
            query = MybatisPlusUtil.customEqQuery(query, "device_type", param.getDeviceType());
            query = MybatisPlusUtil.customEqQuery(query, "device_socket", param.getDeviceSocket());
            query = MybatisPlusUtil.customEqQuery(query, "platform_type", param.getPlatformType());
            query = MybatisPlusUtil.customLikeQuery(query, "imei", param.getImei());
        }

        IPage<DeviceBase> deviceBasePage = deviceBaseManager.page(new Page<DeviceBase>(currentPage, pageSize).setDesc("id"), query);

        List<JSONObject> records = deviceBasePage.getRecords().stream()
                .map(item -> {
                    JSONObject jsonObject = (JSONObject) JSON.toJSON(item);
                    Optional<DeviceType> deviceType = DeviceType.valueOf(item.getDeviceType());
                    Optional<DeviceSocket> deviceSocket = DeviceSocket.valueOf(item.getDeviceSocket());
                    Optional<PlatformType> platformType = PlatformType.valueOf(item.getPlatformType());

                    return jsonObject.fluentPut("deviceType_desc", deviceType.isPresent() ? deviceType.get().toString() : null)
                            .fluentPut("deviceSocket_desc", deviceSocket.isPresent() ? deviceSocket.get().toString() : null)
                            .fluentPut("platformType_desc", platformType.isPresent() ? platformType.get().toString() : null);
                }).collect(Collectors.toList());
        return new JSONObject().fluentPut("total", deviceBasePage.getTotal())
                .fluentPut("records", records);
    }

    @Transactional
    public void add(DeviceBase param, Boolean toWeb, String currentAccount, Date now) {
        try {
            DeviceBase bean = DeviceBase.builder()
                    .deviceType(param.getDeviceType())
                    .deviceSocket(param.getDeviceSocket())
                    .imei(param.getImei())
                    .waveLength(param.getWaveLength())
                    .initDate(param.getInitDate())
                    .platformType(param.getPlatformType())
                    .deviceStatus(1)
                    .remarks(param.getRemarks())
                    .createUser(currentAccount)
                    .updateUser(currentAccount)
                    .ctime(now)
                    .utime(now).build();

            ToWebType toWebType = null;
            if (param.getCompanyId() != null) {
                bean.setCompanyId(param.getCompanyId());
                if (toWeb) {
                    toWebType = resolveToWebType(bean.getDeviceType());
                }
            }


            Verify.isTrue(deviceBaseManager.save(bean), "注册设备失败.");

            if (toWebType != null) {
                companyDeviceWebManager.save(CompanyDeviceWeb.builder()
                        .companyBaseId(param.getCompanyId())
                        .deviceBaseId(bean.getId())
                        .webType(toWebType.getValue())
                        .ctime(now)
                        .build());
            }
        } catch (DuplicateKeyException e) {
            throw new VerifyException("该设备已存在");
        }
    }

    public JSONObject info(Long id) {
        Verify.isTrue(id != null && id > 0, "设备不存在");
        DeviceBase deviceBase = deviceBaseManager.getById(id);
        Verify.notNull(deviceBase, "设备不存在");

        Verify.isTrue(deviceBase.getCompanyId() == null, "设备已分配企业");

        JSONObject result = (JSONObject) JSON.toJSON(deviceBase);
        result.fluentPut("deviceTypeDesc", DeviceType.valueOf(deviceBase.getDeviceType()).get().getDesc())
                .fluentPut("deviceSocketDesc", DeviceSocket.valueOf(deviceBase.getDeviceSocket()).get().getDesc())
                .fluentPut("platformTypeDesc", PlatformType.valueOf(deviceBase.getPlatformType()).get().getDesc());

        return result;
    }

    public void update(DeviceBase param, String currentAccount, Date now) {
        Verify.isTrue(param.getId() != null && param.getId() > 0, "设备不存在");

        DeviceBase deviceBase = deviceBaseManager.getById(param.getId());
        Verify.notNull(deviceBase, "设备不存在");

        DeviceBase toUpdate = DeviceBase.builder()
                .id(param.getId())
                .deviceType(param.getDeviceType())
                .deviceSocket(param.getDeviceSocket())
                .imei(param.getImei())
                .waveLength(param.getWaveLength())
                .initDate(param.getInitDate())
                .platformType(param.getPlatformType())
                .remarks(param.getRemarks())
                .updateUser(currentAccount)
                .utime(now)
                .version(deviceBase.getVersion())
                .build();

        Verify.isTrue(deviceBaseManager.updateById(toUpdate), "更新设备失败");
    }

    public void remove(Long id) {
        if (id != null && id > 0) {
            deviceBaseManager.removeById(id);
        }
    }

    @Transactional
    public void allocation(Long deviceId, Long companyId, Boolean toweb, String currentAccount, Date now) {
        Verify.isTrue(deviceId != null && deviceId > 0, "设备不存在");

        DeviceBase deviceBase = deviceBaseManager.getById(deviceId);
        Verify.notNull(deviceBase, "设备不存在");

        Verify.isTrue(deviceBase.getCompanyId() == null, "设备已分配");

        DeviceBase toUpdate = DeviceBase.builder()
                .id(deviceId)
                .companyId(companyId)
                .updateUser(currentAccount)
                .utime(now)
                .version(deviceBase.getVersion())
                .build();

        ToWebType toWebType = null;
        if (toweb) {
            toWebType = resolveToWebType(deviceBase.getDeviceType());
        }

        Verify.isTrue(deviceBaseManager.updateById(toUpdate), "分配设备失败");

        if (toWebType != null) {
            companyDeviceWebManager.save(CompanyDeviceWeb.builder()
                    .companyBaseId(companyId)
                    .deviceBaseId(deviceId)
                    .webType(toWebType.getValue())
                    .ctime(now)
                    .build());
        }
    }

    private ToWebType resolveToWebType(Integer deviceTypeCode) {
        DeviceType deviceType = DeviceType.valueOf(deviceTypeCode).get();
        if (deviceType == null) {
            return null;
        }

        if (deviceType == DeviceType.TRASH_CAN) {
            return ToWebType.TRASH_CAN_WEB;
        }

        if (deviceType == DeviceType.CAR_PARK || deviceType == DeviceType.CAR_PARK_DUAL) {
            return ToWebType.CAR_PARK_WEB;
        }


        if (deviceType == DeviceType.SEWER_COVER) {
            return ToWebType.SEWER_COVER_WEB;
        }


        if (deviceType == DeviceType.SIGNPOST) {
            return ToWebType.SIGNPOST_WEB;
        }

        return null;
    }
}
